import 'dart:convert';
import 'dart:io';

import 'package:fbutton/fbutton.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_chip/config/Comm.dart';
import 'package:flutter_chip/utils/toast_utils.dart';
import 'package:flutter_chip/widget/view_checkbox.dart';
import 'package:fradio/fradio.dart';
import 'package:fsuper/fsuper.dart';
import 'package:get_ip/get_ip.dart';

import '../widget_period.dart';
import 'bean_client.dart';
import 'data_utils.dart';

class ServerPage extends StatefulWidget {
  @override
  _ServerPageState createState() => _ServerPageState();
}

class _ServerPageState extends State<ServerPage>
    with AutomaticKeepAliveClientMixin {
  ///ip：port输入框
  var _ipController = TextEditingController();
  var _portController = TextEditingController();
  var _sendController = TextEditingController();
  var _recvController = ScrollController();

  ///服务器
  ServerSocket _serverSocket;
  String _serverIp = '';
  int _serverPort = 8080;

  ///已连接的client
  Map<String, Client> mapClient = Map();
  Client currClient = Client();

  @override
  void initState() {
    super.initState();
    initServer();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          _currServer(),
          Offstage(offstage: mapClient.isEmpty, child: _clientLabelWidtet()),
          _recvWidget(),
          _sendWidget(),
        ],
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    _ipController.dispose();
    _portController.dispose();
    _recvController.dispose();
    stopServer();
  }

  ///服务器状态
  Widget _currServer() {
    return FSuper(
      width: Comm.screenWidth,
      height: 40,
      margin: EdgeInsets.all(10),
      padding: EdgeInsets.only(left: 10),
      child1: FSuper(
        height: 40,
        width: Comm.screenWidth,
        text: null == _serverSocket
            ? '未启动：$_serverIp'
            : '已启动：$_serverIp:$_serverPort',
        textSize: 16,
        textColor: Colors.grey,
        textAlignment: Alignment.centerLeft,
        backgroundColor: Color(0xffDEDEDE),
        padding: EdgeInsets.only(left: 10),
        corner: Corner.all(6),
        child1: Icon(Icons.edit, color: Colors.grey),
        child1Margin: EdgeInsets.only(right: 6),
        child1Alignment: Alignment.centerRight,
      ),
      child1Margin: EdgeInsets.only(right: 30, left: 30),
      child1Alignment: Alignment.centerLeft,
      onChild1Click: settingServer,
    );
  }

  ///客户端列表
  Widget _clientLabelWidtet() {
    return Container(
      height: 48,
      width: double.infinity,
      margin: EdgeInsets.symmetric(horizontal: 10),
      child: ListView(
        scrollDirection: Axis.horizontal,
        children: mapClient.values.map((item) {
          String itemIp = '${item.clientIp}:${item.clientPort}';
          String currIp = '${currClient.clientIp}:${currClient.clientPort}';
          return FRadio(
              width: 90,
              height: 48,
              hasSpace: false,
              corner: FRadioCorner.all(0),
              border: 0,
              selectedColor: Color(0xFFEEEEEE),
              child: FSuper(
                backgroundColor: Colors.transparent,
                child1: Icon(Icons.computer),
                child1Alignment: Alignment.topCenter,
                text: itemIp.replaceAll(":", '\n'),
                textAlignment: Alignment.bottomCenter,
                padding: EdgeInsets.only(top: 20),
                textSize: 12,
              ),
              selectedChild: FSuper(
                backgroundColor: Color(0xffEEEEEE),
                child1:
                    Icon(Icons.computer, color: Color(0XFF333333), size: 18),
                child1Alignment: Alignment.topCenter,
                text: itemIp.replaceAll(":", '\n'),
                textColor: Color(0XFF333333),
                textWeight: FontWeight.bold,
                textAlignment: Alignment.bottomCenter,
                padding: EdgeInsets.only(top: 18, bottom: 4, left: 4, right: 4),
                textSize: 12,
              ),
              value: itemIp,
              groupValue: currIp,
              onChanged: (value) {
                currClient = mapClient[value];
                setState(() {});
              });
        }).toList(),
      ),
    );
  }

  ///数据接收区
  Widget _recvWidget() {
    return FSuper(
      width: double.infinity,
      height: 240,
      margin: EdgeInsets.only(left: 10, right: 10),
      text: "数据接收区",
      textColor: Colors.grey,
      padding: EdgeInsets.all(6),
      textAlignment: Alignment.topLeft,
      textAlign: TextAlign.left,
      child1Margin: EdgeInsets.only(top: 10),
      backgroundColor: Color(0xffEEEEEE),
      child1: Container(
        width: Comm.screenWidth - 110,
        height: 216,
        margin: EdgeInsets.only(left: 10, right: 10, top: 20, bottom: 10),
        child: ListView(
          controller: _recvController,
          children: <Widget>[
            Text(currClient.recvData),
          ],
        ),
      ),
      child1Alignment: Alignment.centerLeft,
      child2Alignment: Alignment.bottomRight,
      child2: Column(
        mainAxisSize: MainAxisSize.min,
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          FSuper(
            width: 84,
            height: 24,
            text: 'TX：${currClient.txNum}',
            textAlignment: Alignment.centerLeft,
            padding: EdgeInsets.only(left: 10),
          ),
          FSuper(
            width: 84,
            height: 24,
            text: 'RX：${currClient.rxNum}',
            textAlignment: Alignment.centerLeft,
            padding: EdgeInsets.only(left: 10),
          ),
          FSuper(
            height: 32,
            width: 76,
            text: "计数清零",
            textSize: 12,
            textAlignment: Alignment.center,
            backgroundColor: Color(0xffDDDDDD),
            corner: Corner.all(6),
            onClick: () {
              setState(() {
                currClient.rxNum = 0;
                currClient.txNum = 0;
              });
            },
          ),
          Container(child: Divider(), width: 84),
          MyCheckBox(
            "自动换行",
            currClient.autoSend,
            (value) => currClient.autoSend = value,
          ),
          SizedBox(height: 6),
          MyCheckBox(
            "HEX显示",
            currClient.showHex,
            (value) => currClient.showHex = value,
          ),
          SizedBox(height: 6),
          FSuper(
            height: 32,
            width: 76,
            text: "清除显示",
            textSize: 12,
            textAlignment: Alignment.center,
            backgroundColor: Color(0xffdddddd),
            corner: Corner.all(6),
            onClick: () {
              setState(() {
                currClient.recvData = '';
              });
            },
          ),
          SizedBox(height: 6),
        ],
      ),
    );
  }

  ///发送数据
  Widget _sendWidget() {
    return FSuper(
      width: double.infinity,
      height: 110,
      text: '数据发送区',
      textColor: Colors.grey,
      backgroundColor: Color(0xFFEEEEEE),
      corner: Corner.all(6),
      textAlignment: Alignment.topLeft,
      margin: EdgeInsets.only(left: 10, right: 10, top: 10),
      padding: EdgeInsets.only(left: 6, top: 6),
      child1Margin: EdgeInsets.only(bottom: 8),
      child1: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          MyCheckBox(
            "HEX发送",
            currClient.sendHex,
            (value) => currClient.showHex = value,
          ),
          MyCheckBox(
            "自动发送",
            currClient.autoSend,
            (value) => currClient.autoSend = value,
          ),
          PeriodWidget(
            currClient.period,
            (period) => currClient.period = period,
          ),
        ],
      ),
      child2: FSuper(
        width: double.infinity,
        height: 36,
        child1: Container(
          width: Comm.screenWidth - 84,
          height: 36,
          child: TextField(
            controller: _sendController,
            decoration: InputDecoration(
              hintText: "发送数据",
              hintStyle: TextStyle(fontSize: 12),
              contentPadding: EdgeInsets.all(10),
              border: OutlineInputBorder(
                borderSide: BorderSide(),
                borderRadius: BorderRadius.all(Radius.circular(6)),
              ),
            ),
          ),
        ),
        child1Margin: EdgeInsets.only(left: 6),
        child2Margin: EdgeInsets.only(right: 6),
        child1Alignment: Alignment.centerLeft,
        child2Alignment: Alignment.centerRight,
        child2: FButton(
          onPressed: _sendData,
          width: 48,
          height: 36,
          padding: EdgeInsets.zero,
          text: '发送',
          fontSize: 12,
          textColor: Colors.white,
          corner: FButtonCorner.all(4),
          effect: true,
          clickEffect: true,
          color: Theme.of(context).accentColor,
        ),
      ),
      child2Margin: EdgeInsets.only(bottom: 6),
      child2Alignment: Alignment.bottomCenter,
    );
  }

  ///服务器设置
  void settingServer() {
    showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text('添加服务器'),
            content: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                TextField(
                  controller: _ipController,
                  decoration: InputDecoration(
                    labelText: "IP地址",
                    enabled: _serverIp.isEmpty,
                    hintStyle: TextStyle(fontSize: 12),
                    contentPadding: EdgeInsets.all(10),
                    border: OutlineInputBorder(
                      borderSide: BorderSide(),
                      borderRadius: BorderRadius.all(Radius.circular(6)),
                    ),
                  ),
                ),
                SizedBox(height: 6),
                TextField(
                  controller: _portController,
                  keyboardType: TextInputType.number,
                  decoration: InputDecoration(
                    labelText: "端口号",
                    hintText: "请输入端口号",
                    hintStyle: TextStyle(fontSize: 12),
                    contentPadding: EdgeInsets.all(10),
                    border: OutlineInputBorder(
                      borderSide: BorderSide(),
                      borderRadius: BorderRadius.all(Radius.circular(6)),
                    ),
                  ),
                ),
              ],
            ),
            actions: <Widget>[
              FlatButton(
                onPressed: () {
                  Navigator.pop(context);
                },
                child: Text("取消"),
              ),
              FlatButton(
                onPressed: () {
                  if (_portController.text.isEmpty) {
                    Toast.show("请输入端口号");
                    return;
                  }
                  setState(() {
                    _serverIp = _ipController.text;
                    _serverPort = int.parse(_portController.text);
                  });
                  startServer();
                  Navigator.pop(context);
                },
                child: Text("确定"),
              ),
            ],
          );
        });
  }

  ///启动服务器
  void startServer() async {
    if (null != _serverSocket) {
      _serverSocket.close();
    }
    await ServerSocket.bind(_serverIp, _serverPort)
        .then((ServerSocket serverSocket) {
      setState(() {
        _serverSocket = serverSocket;
      });
      Toast.show('服务已启动');
    });
    _serverSocket.listen((Socket socket) {
      String remoteIp = '${socket.remoteAddress.host}:${socket.remotePort}';
      Client client = Client();
      client.clientIp = socket.remoteAddress.host;
      client.clientPort = socket.remotePort;
      client.socket = socket;
      setState(() {
        mapClient[remoteIp] = client;
        currClient = client;
      });
      if (mapClient.length > 5) {
        _serverSocket.close();
        Toast.show('已到连接上线');
      }
      print('已连接：${client.toJson()}');
      Toast.show('$remoteIp已连接');
      socket.listen((data) {
        print("[$remoteIp]:$data");
        setRecvData(mapClient[remoteIp], data);
      }).onDone(() {
        Toast.show('[$remoteIp]已断开连接');
        mapClient.remove(remoteIp);
        if (remoteIp == '${client.clientIp}:${client.clientPort}') {
          if (mapClient.length > 0) {
            currClient = mapClient[mapClient.keys.last];
          } else {
            currClient = Client();
          }
        }
        if (!mounted) {
          setState(() {});
        }
      });
    });
  }

  ///更新客户端收到的数据
  void setRecvData(Client client, List<int> data) {
    if (null == client) {
      return;
    }
    client.rxNum += data.length;
    String currIp = '${currClient.clientIp}:${currClient.clientPort}';
    try {
      String recv = '';
      if (client.showHex) {
        data.forEach((byte) {
          recv += '${byte.toRadixString(16).toUpperCase()} ';
        });
      } else {
        recv = '${ascii.decode(data)}';
      }
      client.recvData += '$recv${client.autoLine ? '\n' : ''}';
      if (currIp == '${client.clientIp}:${client.clientPort}') {
        setState(() {});
        _recvController.jumpTo(_recvController.position.maxScrollExtent);
      }
    } on FormatException catch (error) {
      print(error.toString());
    }
  }

  ///停止服务器
  void stopServer() {
    if (null == _serverSocket) {
      return;
    }
    if (null != _serverSocket) {
      _serverSocket.close();
    }
    try {
      ///关闭所有客户端连接
      mapClient.forEach((key, Client client) {
        if (null != client.socket) {
          client.socket.destroy();
          print("关闭$key");
        }
      });
    } catch (e) {
      print('$e');
    }
  }

  ///初始化服务器IP地址
  void initServer() async {
    String tmpIp = await GetIp.ipAddress;
    if (tmpIp.isNotEmpty) {
      _ipController.value = TextEditingValue(text: tmpIp);
      setState(() {
        _serverIp = tmpIp;
      });
    }
  }

  ///发送数据
  void _sendData() {
    if (_sendController.text.isEmpty) {
      Toast.show('请输入发送内容');
      return;
    }
    if (null == currClient.socket) {
      Toast.show('请先连接服务器');
      return;
    }
    String sendStr = _sendController.text;
    if (currClient.sendHex) {
      List<int> hexs = List();
      List<String> tmpList = sendStr.split(' ');
      try {
        tmpList.forEach((hexData) {
          int tmpData = DataUtils.hexToInt(hexData);
          hexs.add(tmpData);
        });
        print('发送原始值：$hexs');
        currClient.txNum += hexs.length;
        currClient.socket.add(hexs);
      } catch (e) {
        Toast.show('请输入正确16进制值，不包含0X，多个用空格隔开');
      }
    } else {
      currClient.txNum += ascii.encode(sendStr).length;
      currClient.socket.add(ascii.encode(sendStr));
    }
    setState(() {});
    if (currClient.autoSend) {
      Future.delayed(Duration(milliseconds: currClient.period))
          .then((value) => _sendData());
    }
  }

  @override
  bool get wantKeepAlive => true;
}
